from machine import Pin
import time

# 定义TM1650类
class TM1650:
    ADDR_DIS = 0x48  # 加密模式命令
    ADDR_KEY = 0x49  # 读键值命令

    BRIGHT_DARKEST = 0
    BRIGHT_TYPICAL = 2
    BRIGHTEST = 7

    on = 1
    off = 0

    # 数码管显示的数字
    NUM = [0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f]
    # 数码管显示的点
    DIG = [0x6e, 0x6c, 0x6a, 0x68]
    # 数码管显示的点
    DOT = [0, 0, 0, 0]

    def __init__(self, clk_pin, dio_pin):
        # 初始化时钟引脚和数据引脚
        self.clkPin = clk_pin
        self.dioPin = dio_pin
        # 设置时钟引脚为输出模式
        self.clk = Pin(self.clkPin, Pin.OUT)
        # 设置数据引脚为输出模式
        self.dio = Pin(self.dioPin, Pin.OUT)
        # 初始化显示命令
        self.DisplayCommand = 0
        # 初始化数码管
        self.InitDigitalTube()

    def writeByte(self, wr_data):
        # 循环8次，将wr_data写入数码管
        for i in range(8):
            # 如果wr_data的最高位为1，则将数据引脚置为高电平
            if wr_data & 0x80 == 0x80:
                self.dio.value(1)
            # 否则将数据引脚置为低电平
            else:
                self.dio.value(0)
            # 将时钟引脚置为低电平
            self.clk.value(0)
            # 延时0.0001秒
            time.sleep(0.0001)
            # 将时钟引脚置为高电平
            self.clk.value(1)
            # 延时0.0001秒
            time.sleep(0.0001)
            # 将时钟引脚置为低电平
            self.clk.value(0)
            # 将wr_data左移一位
            wr_data <<= 1
        return

    def start(self):
        # 设置dio引脚为高电平
        self.dio.value(1)
        # 设置clk引脚为高电平
        self.clk.value(1)
        # 等待0.0001秒
        time.sleep(0.0001)
        # 设置dio引脚为低电平
        self.dio.value(0)
        return

    def ack(self):
        # 初始化dy为0
        dy = 0
        # 设置clk引脚为低电平
        self.clk.value(0)
        # 等待0.0001秒
        time.sleep(0.0001)
        # 将dio引脚设置为输入模式
        self.dio = Pin(self.dioPin, Pin.IN)
        # 当dio引脚为高电平时，循环等待
        while self.dio.value() == 1:
            # 等待0.0001秒
            time.sleep(0.0001)
            # dy加1
            dy += 1
            # 如果dy大于5000，跳出循环
            if dy > 5000:
                break
        # 设置clk引脚为高电平
        self.clk.value(1)
        # 等待0.0001秒
        time.sleep(0.0001)
        # 设置clk引脚为低电平
        self.clk.value(0)
        # 将dio引脚设置为输出模式
        self.dio = Pin(self.dioPin, Pin.OUT)
        return

    def stop(self):
        self.dio.value(0)
        self.clk.value(1)
        time.sleep(0.0001)
        self.dio.value(1)
        return

    def displayBit(self, bit, num):
        if num > 9 and bit > 4:
            return
        self.start()
        self.writeByte(self.ADDR_DIS)
        self.ack()
        self.writeByte(self.DisplayCommand)
        self.ack()
        self.stop()
        self.start()
        self.writeByte(self.DIG[bit - 1])
        self.ack()
        if self.DOT[bit - 1] == 1:
            self.writeByte(self.NUM[num] | 0x80)
        else:
            self.writeByte(self.NUM[num])
        self.ack()
        self.stop()
        return

    def clearBit(self, bit):
        if bit > 4:
            return
        self.start()
        self.writeByte(self.ADDR_DIS)
        self.ack()
        self.writeByte(self.DisplayCommand)
        self.ack()
        self.stop()
        self.start()
        self.writeByte(self.DIG[bit - 1])
        self.ack()
        self.writeByte(0x00)
        self.ack()
        self.stop()
        return

    def setBrightness(self, b=BRIGHT_TYPICAL):
        self.DisplayCommand = (self.DisplayCommand & 0x0f) + (b << 4)
        return

    def setMode(self, segment=0):
        self.DisplayCommand = (self.DisplayCommand & 0xf7) + (segment << 3)
        return

    def displayOnOFF(self, OnOff=1):
        self.DisplayCommand = (self.DisplayCommand & 0xfe) + OnOff
        return

    def displayDot(self, bit, OnOff):
        if bit > 4:
            return
        if OnOff == 1:
            self.DOT[bit - 1] = 1
        else:
            self.DOT[bit - 1] = 0
        return

    def InitDigitalTube(self):
        self.setBrightness(2)
        self.setMode(0)
        self.displayOnOFF(1)
        for _ in range(4):
            self.clearBit(_)
        return

    def ShowNum(self, num):  # 0~9999
        self.displayBit(1, num % 10)
        if num < 10:
            self.clearBit(2)
            self.clearBit(3)
            self.clearBit(4)
        if num > 9 and num < 100:
            self.displayBit(2, num // 10 % 10)
            self.clearBit(3)
            self.clearBit(4)
        if num > 99 and num < 1000:
            self.displayBit(2, num // 10 % 10)
            self.displayBit(3, num // 100 % 10)
            self.clearBit(4)
        if num > 999 and num < 10000:
            self.displayBit(2, num // 10 % 10)
            self.displayBit(3, num // 100 % 10)
            self.displayBit(4, num // 1000)
